from django.shortcuts import redirect
from django.db.models.aggregates import Avg, Count
from django.http import (HttpResponse, HttpResponseNotFound,
                         HttpResponseBadRequest, HttpResponseForbidden)
from django.utils import simplejson as json
from django.core.urlresolvers import reverse

from shop.models import Rating, Product



def ajax_rate(request, product_id, stars):
    """Creates or updates a user rating object (Ratings).

    Returns a new average rating for the product as a JSON response

    """
    # not allowed to rate
    if not request.user.is_authenticated():
        return HttpResponseForbidden()

    # fetch product
    try:
        product = Product.objects.get(id=int(product_id))
    except Product.DoesNotExist:
        return HttpResponseNotFound()

    # validate rating value
    stars = int(stars)
    if stars > 5 or stars < 1:
        return HttpResponseBadRequest()

    # find existing rating by (product,user)
    try:
        rating = Rating.objects.get(
                user = request.user,
                product = product
        )
        # update rating value on existing rating
        rating.stars = stars

    # create a new rating
    except Rating.DoesNotExist:
        rating = Rating.objects.create(
            user = request.user,
            product = product,
            stars = stars
        )

    rating.save()

    # calculate a new average rating and total count of ratings for the
    # product in DB
    rating = Rating.objects.filter(product=product_id) \
                           .aggregate(stars=Avg('stars'), count=Count('stars'))
    stars = rating['stars']
    if stars is None:
        stars = 0

    # output json
    content = json.dumps({
        'rating': stars,
        'votes':  rating['count']
    })
    return HttpResponse(content, mimetype='application/json')


def form_rate(request):
    """Invokes the ajax-version (ajax_rate) of rating and redirects to the same
    page where action was submitted from. No checking for errors in ajax_rate

    """
    product_id = request.POST.get('product_id', '0')
    rating = request.POST.get('rating', '0')
    ajax_rate(request, product_id, rating)
    referer = request.META.get('HTTP_REFERER', reverse('shop.views.product.list', None))
    return redirect(referer)
